package blackstar.agent.web;

import java.security.Principal;
import java.util.List;

import org.mortbay.jetty.Request;
import org.mortbay.jetty.security.UserRealm;

import blackstar.agent.security.SecurityUser;
import blackstar.agent.security.UserManager;

public class AgentUserRealm implements UserRealm
{
	private UserManager userManager;

	public AgentUserRealm(UserManager userManager)
	{
		this.userManager = userManager;
	}

	public Principal authenticate(String username, Object credentials,
			Request request)
	{
		SecurityUser securityUser = this.userManager.findUser(username);
		if (securityUser == null)
		{
			return null;
		}

		KnownUser user = new KnownUser(securityUser);
		if (user.authenticate(credentials))
		{
			return user;
		}
		else
		{
			return null;
		}
	}

	public void disassociate(Principal principal)
	{
	}

	public String getName()
	{
		return "AgentUserRealm";
	}

	public Principal getPrincipal(String username)
	{
		SecurityUser securityUser = this.userManager.findUser(username);
		if (securityUser == null)
		{
			return null;
		}
		return (Principal) new KnownUser(securityUser);
	}

	public synchronized boolean isUserInRole(Principal user, String roleName)
	{
		if (user instanceof WrappedUser)
		{
			return ((WrappedUser) user).isUserInRole(roleName);
		}
		if (user == null || !(user instanceof User)
				|| ((User) user).getUserRealm() != this)
		{
			return false;
		} else
		{
			SecurityUser securityUser = this.userManager
					.findUser(((User) user).getName());
			if (securityUser == null)
			{
				return false;
			} else
			{
				return securityUser.isRole(roleName);
			}
		}
	}

	public void logout(Principal principal)
	{
	}

	public Principal pushRole(Principal user, String role)
	{
		if (user == null)
		{
			user = new User();
		}
		return new WrappedUser(user, role);
	}

	public Principal popRole(Principal user)
	{
		WrappedUser wu = (WrappedUser) user;
		return wu.getUserPrincipal();
	}

	public boolean reauthenticate(Principal user)
	{
		return ((User) user).isAuthenticated();
	}

	private class WrappedUser extends User
	{
		Principal getUserPrincipal()
		{
			return user;
		}

		public String getName()
		{
			return "role:" + role;
		}

		public boolean isAuthenticated()
		{
			return true;
		}

		public boolean isUserInRole(String role)
		{
			return this.role.equals(role);
		}

		private Principal user;
		private String role;

		WrappedUser(Principal user, String role)
		{
			super();
			this.user = user;
			this.role = role;
		}
	}

	private class KnownUser extends User
	{

		boolean authenticate(Object credentials)
		{
			return this.securityUser.authenticate(credentials);
		}

		public String getName()
		{
			return this.securityUser.getName();
		}

		public boolean isAuthenticated()
		{
			return true;
		}

		private SecurityUser securityUser;

		KnownUser(SecurityUser securityUser)
		{
			super();
			this.securityUser = securityUser;
		}
	}

	private class User implements Principal
	{

		private UserRealm getUserRealm()
		{
			return AgentUserRealm.this;
		}

		public String getName()
		{
			return "Anonymous";
		}

		public boolean isAuthenticated()
		{
			return false;
		}

		public String toString()
		{
			return getName();
		}

		List roles;

		private User()
		{
			super();
			roles = null;
		}

	}
}